Football Player Injury Risk Analysis

Football
Author

Gareth Edwards

Published

May 25, 2026

Listen, football injuries aren’t cool. I’ve elaborated on this in depth in my previous blog post so let me not bore you with further ramblings.

We know how critical injury prevention is for a Premier League team who want to win the league. The average number of gameweeks missed per player for a team closely correlates with that team’s final league position, and this is especially true for the top sides in England. The margins are extremely fine. The plot below shows us that teams who maintain lower average gameweeks missed per player are far more likely to finish in the top two. Or in other words, teams who top the average-gameweeks-missed-per-player board (with the lowest number) are most likely to also top the Premier League table!

Figure 1: Average Gameweeks Missed vs. League Finish

This begs the question, how can a team prevent these injuries from happening? The answer may be found in survival analysis. Survival analysis models the time to an event and has the ability to convert this to a risk score over time. It helps the coaching staff and physio staff to know, at a given time, what is the injury risk score of player x.

The approach I took was to loosely follow the study by Catrell et al. (Catterall et al. 2026). Here a Survival Analysis was carried out on the SoccerMon dataset (Midoglu et al. 2022). SoccerMon is “A Large-Scale Multivariate Soccer Athlete Health, Performance, and Position Monitoring Dataset”. SoccerMon is the largest soccer athlete dataset available that tracks both subjective (using questionnaire methods) and objective features (using GPS trackers and other sensors). The data comes from two teams from the Norwegian women’s elite soccer league over the span of two years (2020-2021).

I used this paper to inform which features I extract from the SoccerMon dataset. Below is a list of the features I extracted. Each feature represents a 21 day moving average of that feature.

Feature Definition Type
player_name Unique identifier/name of the player.
date Date of the observation or training session.
ATL Acute Training Load objective
Weekly load Total accumulated training load over the last week. objective
Monotony Training monotony metric objective
Strain Training strain metric objective
ACWR Acute:Chronic Workload Ratio objective
CTL28 Chronic Training Load calculated over the previous 28 days. objective
CTL42 Chronic Training Load calculated over the previous 42 days. objective
Fatigue Self-reported fatigue score from the wellness questionnaire. subjective
Mood Self-reported mood score from the wellness questionnaire. subjective
Readiness Self-reported readiness-to-train score. subjective
Sleep duration Number of hours slept prior to the report. subjective
Soreness Self-reported muscle soreness score. subjective
Stress Self-reported stress level score. subjective
daily_load Total training load accumulated on that day. objective
sRPE Session Rating of Perceived Exertion load, typically session duration × RPE. objective
duration obj Objectively measured session duration. objective
RPE Rating of Perceived Exertion reported by the athlete after the session. subjective
Speed_km_h_mean Mean speed recorded during the session (km/h). objective
Speed_km_h_max Maximum speed recorded during the session (km/h). objective
Speed_km_h_std Standard deviation of speed during the session. objective
Distance Total distance covered during the session. objective
distance_per_min Average distance covered per minute of activity. objective
total_time_min Total duration of the session in minutes. objective
sp_lir_t Time spent in the Low-Intensity Running speed zone. objective
sp_lir_d Distance covered in the Low-Intensity Running speed zone. objective
sp_lir_p Percentage of total session spent in the Low-Intensity Running speed zone. objective
sp_mir_t Time spent in the Moderate-Intensity Running speed zone. objective
sp_mir_d Distance covered in the Moderate-Intensity Running speed zone. objective
sp_mir_p Percentage of total session spent in the Moderate-Intensity Running speed zone. objective
sp_hir_t Time spent in the High-Intensity Running speed zone. objective
sp_hir_d Distance covered in the High-Intensity Running speed zone. objective
sp_hir_p Percentage of total session spent in the High-Intensity Running speed zone. objective
sp_spr_t Time spent sprinting. objective
sp_spr_d Distance covered while sprinting. objective
sp_spr_p Percentage of total session spent sprinting. objective
has_gps_data Indicator that GPS measurements are available for the session. objective
has_session_data Indicator that session/training load data are available. objective
wellness_reported Indicator that the athlete completed the wellness questionnaire. objective
is_rest_day Indicator that the day was designated as a rest day. objective
is_injured_today Indicator that the player was injured on the given date. objective
injury_onset Indicator marking the first day of an injury event. objective
event Survival-analysis event indicator objective
time_to_event Survival-analysis time-to-event variable (days) derived

Extensive EDA and necessary transformations (StandardScaler for columns with a normal distribution and Yeo-Johnson scaling for skewed data) were applied. These transformations help the model see the patterns in the data better as it places all the numbers on the same scale. Without transformations any column with large numbers like Speed_km_h_mean compared to columns with smaller numbers like ACWR will dominate the model during training.

Two further features were added to the dataset, and that was event and time-to-event. Where event is a boolean value (0 or 1) denoting if a player got injured within the next seven days (1) or not (0). Time-to-event was the number of days leading up to the event (starting at 7 days back). See an example of the unscaled dataset below:

player_name date is_injured_today injury_onset event duration ATL Weekly load Monotony Strain ... sp_hir_t sp_hir_d sp_hir_p sp_spr_t sp_spr_d sp_spr_p has_gps_data has_session_data wellness_reported is_rest_day
1143 TeamB-29c5271b-5c46-455e-91ea-da2abfa8ff3c 2020-08-10 0 0 0 7 233.673333 1635.714286 1.699048 2900.757143 ... 0.060317 0.021745 0.000379 0.000317 0.000133 0.000001 0.285714 0.857143 0.809524 0.142857
1144 TeamB-29c5271b-5c46-455e-91ea-da2abfa8ff3c 2020-08-11 0 0 0 7 239.047619 1673.333333 1.743333 2987.342857 ... 0.071905 0.026021 0.000443 0.001429 0.000605 0.000007 0.333333 0.857143 0.809524 0.142857
1145 TeamB-29c5271b-5c46-455e-91ea-da2abfa8ff3c 2020-08-12 0 0 0 7 243.197619 1702.380952 1.778095 3060.814286 ... 0.139524 0.050366 0.001400 0.006984 0.003020 0.000086 0.380952 0.809524 0.809524 0.190476
1146 TeamB-29c5271b-5c46-455e-91ea-da2abfa8ff3c 2020-08-13 0 0 0 7 244.490476 1711.428571 1.800000 3100.466667 ... 0.139524 0.050366 0.001400 0.006984 0.003020 0.000086 0.380952 0.809524 0.809524 0.190476
1147 TeamB-29c5271b-5c46-455e-91ea-da2abfa8ff3c 2020-08-14 0 0 0 7 243.878571 1707.142857 1.803810 3099.347619 ... 0.182540 0.066014 0.001636 0.007619 0.003287 0.000090 0.428571 0.809524 0.809524 0.190476

5 rows × 45 columns

So, how do we use these features to inform us whether a player is at a high risk of injury or not? Well, this is where Survival Analysis comes into play. For this problem I have used the Random Forest Survival model and trained it on the features we see above using a leave one player out process. This means the model was trained on every player except one and then the trained model was applied to that one player to mimic a real world application. This process was repeated with each player.

The results are promising! The plots below show player injury risk over time with a vertical line showing where an injury actually occured. Notice how the injuries always occur around where an increased injury risk is!

Figure 2: Injury Risk Overtime for Player A
Figure 3: Injury Risk Overtime for Player B
Figure 4: Injury Risk Overtime for Player C

These plots visualise how the risk value corresponds with actual injury periods. Before each injury there is a peak in injury risk. This can serve as an incredibly valuable tool in managing player load and injury prevention. One may note that there are periods of heightened injury risk where no injury ultimately occurs. This is simply the nature of the sport. A player may be teetering on the edge, but through a combination of luck and good, intuitive management by the coaching staff, they avoid injury and remain available for those all-important gameweek fixtures.

Notice the C-index score at the bottom left of each plot. The c-index means essentially how well the model ranks danger rather than predicting exact futures. Because sports injuries are relatively rare, the model could theoretically be 99% “accurate” simply by guessing that no one ever gets hurt (which is completely useless to a coaching staff).

Instead, the C-index grades the model like an Emergency Room triage nurse. Just as a triage nurse doesn’t predict exactly when a patient will heal but correctly prioritizes someone with chest pains over someone with a paper cut, the C-index evaluates prioritisation. It looks at a player’s timeline and asks: If we randomly pick one healthy training day and one actual pre-injury day, did the model correctly assign a higher risk score to the dangerous day? A score of 0.50 means the model is effectively flipping a coin, 0.70 indicates a solid ranking ability, and anything over 0.80 means you have a highly reliable early-warning system to keep your squad on the pitch.

These risk scores are great at finding portions in the season where a player may get injured, but what does the coach or physio do about this? It will be very difficult to tell the coach to go easy on a player just because a blue line is high and not low. And then again, what does “go easy on a player” even mean? Does that mean don’t play them in the next match, give them a day off, just give them light drills, etc?

SHAP analysis can answer these questions, not just on a global level but at a player specific level! Take a look at the SHAP values below for Player A and Player B.

Figure 5: Feature Influence for Player A
Figure 6: Feature Influence for Player B
Figure 7: Feature Influence for Player C

These plots are known as beeswarm plots. Each dot represents a feature’s scores for a specific day, the colour of that dot represents whether the score for that feature was high (red) or low (blue) and the position of the dot tells us if the feature value pushed the model to predict a higher risk of injury (right) or lower risk of injury (left)

Let’s zoom in on what we are seeing for Player A:

Now let’s zoom in on Player B:

Player C seems to follow a similar pattern portrayed for Player A and B with regards to mood, fatigue and soreness.

Conclusion

Survival analysis is a great tool to mitigate player injuries for a sports team with a Random Forest Survival model being one of the highest performing models for this task. While injury risk overtime is great, understanding what drives that risk up or down is equally as important.

Features that drive risk scores are not always intuitive and differ from player to player. For one player higher intensity training may actually reduce injury risk. Some intuitive features show that increased levels of perceived soreness and fatigue lead to injury risk. More unintuitive outcomes show that higher than normal mood scores actually increase risk injury. Given that mood score is a very subjective metric it is difficult to say what one player means to be a “good” mood compared to another.

Overall, there is considerable promise in combining Survival Analysis with SHAP-based interpretability at the individual player level to quantify and understand injury risk over time.

References

Catterall, Victoria, Cise Midoglu, and Stephen Lynch. 2026. Time-to-Injury Forecasting in Elite Female Football: A DeepHit Survival Approach. https://arxiv.org/abs/2601.19479.
Midoglu, Cise, Matthias Boeker, Andreas Kjæreng Winther, et al. 2022. “SoccerMon: A Large-Scale Multivariate Soccer Athlete Health, Performance, and Position Monitoring Dataset.” Version v1. Zenodo. https://doi.org/10.5281/zenodo.10033832.